#include <iostream>
#include <sstream>
#include "Poco/AutoPtr.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "usk/core/usk_core.h"


#include "Poco/AutoPtr.h"
#include "Poco/Logger.h"
#include "Poco/LoggingFactory.h"
#include "Poco/Util/LoggingConfigurator.h"
#include "Poco/Util/PropertyFileConfiguration.h"
#include "cppmicroservices/em/EMConstants.hpp"

#include "cppmicroservices/em/Event.hpp"
#include "cppmicroservices/em/EventHandler.hpp"

using Poco::AutoPtr;
using Poco::Util::AbstractConfiguration;
using Poco::Util::Application;
using Poco::Util::HelpFormatter;
using Poco::Util::Option;
using Poco::Util::OptionCallback;
using Poco::Util::OptionSet;


class MyEventHandler : public cppmicroservices::service::em::EventHandler {
public:
    MyEventHandler() : cppmicroservices::service::em::EventHandler() {}
    void HandleEvent(cppmicroservices::service::em::Event const &evt) override {
        LOG_DEBUG("MyEventHandler::HandleEvent Topic = {}", evt.GetTopic());
    }
};

class USKCoreTestApplication : public Application
{
public:
    USKCoreTestApplication() {}

protected:
    void initialize(Application &self) {
        loadConfiguration(); // load default configuration files, if present
        Application::initialize(self);
        // add your own initialization code here
        try {
            for (auto i = 1; i <= 10; i++) {
                LOG_DEBUG("Message Loop:{}", i);
            }
            LOG_DEBUG("TEST");
            usk::core::OSGI::GetInstance().Init();
            LOG_DEBUG("After OSGI Init");
            auto &core = usk::core::OSGI::GetInstance();
            auto bundle_context = core.GetBundleContext();
            auto logservice_reference = bundle_context.GetServiceReference<cppmicroservices::logservice::LogService>();
            if (logservice_reference) {
                auto log_service =
                        bundle_context.GetService<cppmicroservices::logservice::LogService>(logservice_reference);
                log_service->getLogger("albert")->debug("test message");
            }
        } catch (...) {
            int a = 10;
        }
    }

    void uninitialize() {
        // add your own uninitialization code here
        Application::uninitialize();
        usk::core::OSGI::GetInstance().UnInit();
    }

    void reinitialize(Application &self) {
        Application::reinitialize(self);
        // add your own reinitialization code here
    }

    void defineOptions(OptionSet &options) { Application::defineOptions(options); }

    void handleHelp(const std::string &name, const std::string &value) {
        displayHelp();
        stopOptionsProcessing();
    }

    void handleDefine(const std::string &name, const std::string &value) { defineProperty(value); }

    void handleConfig(const std::string &name, const std::string &value) { loadConfiguration(value); }

    void displayHelp() {
        HelpFormatter helpFormatter(options());
        helpFormatter.setCommand(commandName());
        helpFormatter.setUsage("OPTIONS");
        helpFormatter.setHeader("A sample application that demonstrates some of the features of the "
                                "Poco::Util::Application class.");
        helpFormatter.format(std::cout);
    }

    void defineProperty(const std::string &def) {
        std::string name;
        std::string value;
        std::string::size_type pos = def.find('=');
        if (pos != std::string::npos) {
            name.assign(def, 0, pos);
            value.assign(def, pos + 1, def.length() - pos);
        } else
            name = def;
        config().setString(name, value);
    }

    void testLog() {
        Poco::AutoPtr<Poco::Util::PropertyFileConfiguration> default_config(
                new Poco::Util::PropertyFileConfiguration());
        // 设置日志输出格式  2025-01-01.100 [Debug]:debug info
        default_config->setString("logging.formatters.f1.class", "PatternFormatter");
        default_config->setString("logging.formatters.f1.pattern", "%Y-%m-%d %H:%M:%S.%i [%p][%s]:%t");

        // 控制台日志输出
        default_config->setString("logging.channels.console.class", "ConsoleChannel");
        default_config->setString("logging.channels.console.formatter", "f1");

        // 文件日志输出
        std::string self_path = Poco::Path::self();
        Poco::Path self(self_path);
        auto base_name = self.getBaseName();
        auto log_path = self.parent().pushDirectory("logs");
        log_path.setBaseName(base_name).setExtension("log");
        std::string log_path_string = log_path.toString();

        default_config->setString("logging.channels.file.class", "FileChannel");
        default_config->setString("logging.channels.file.formatter", "f1");
        default_config->setString("logging.channels.file.path", log_path_string);
        default_config->setString("logging.channels.file.rotation", "daily");
        default_config->setString("logging.channels.file.archive", "timestamp");

        // 输出通道
        default_config->setString("logging.channels.splitter.class", "SplitterChannel");
        default_config->setString("logging.channels.splitter.channels", "console,file");

        default_config->setString("logging.loggers.root.channel", "splitter");
        default_config->setString("logging.loggers.root.level", "debug");

        Poco::Util::LoggingConfigurator log_configurator;
        log_configurator.configure(default_config);

        // Poco::Logger& logger = Poco::Logger::get("MyLogger");
        Poco::Logger &rootLog = Poco::Logger::root();
        Poco::Logger &uskLog = Poco::Logger::get("usk.core");
    }

    int main(const ArgVec &args) {
        auto core = usk::core::OSGI::GetInstance();
        auto bundles = core.GetBundles();

        auto bundle_context = core.GetBundleContext();
        cppmicroservices::ServiceProperties properties;
        properties[cppmicroservices::em::Constants::EVENT_TOPIC] = std::string("org/huawei1");
        bundle_context.RegisterService<cppmicroservices::service::em::EventHandler>(std::make_shared<MyEventHandler>(),
                                                                                    properties);

        cppmicroservices::service::em::Event send_event("org/huawei");
        cppmicroservices::service::em::Event post_event("org/huawei");
        core.SendEvent(send_event);
        core.PostEvent(post_event);

        std::string self_path = Poco::Path::self();
        Poco::Path self(self_path);
        auto base_name = self.getBaseName();
        auto log_path = self.parent().pushDirectory("logs");
        Poco::File directory(log_path);
        try {
            // 3. 创建目录（若父目录不存在会自动创建）
            directory.createDirectories(); // 关键方法
        } catch (const Poco::Exception &e) {
            std::cerr << "目录创建失败: " << e.displayText() << std::endl;
        }

        log_path.setBaseName(base_name).setExtension("log");
        std::string s = log_path.toString();

        testLog();

        _sleep(5000);

        return Application::EXIT_OK;
    }

    void printProperties(const std::string &base) {
        AbstractConfiguration::Keys keys;
        config().keys(base, keys);
        if (keys.empty()) {
            if (config().hasProperty(base)) {
                std::string msg;
                msg.append(base);
                msg.append(" = ");
                msg.append(config().getString(base));
                logger().information(msg);
            }
        } else {
            for (AbstractConfiguration::Keys::const_iterator it = keys.begin(); it != keys.end(); ++it) {
                std::string fullKey = base;
                if (!fullKey.empty())
                    fullKey += '.';
                fullKey.append(*it);
                printProperties(fullKey);
            }
        }
    }

private:
};

POCO_APP_MAIN(USKCoreTestApplication)
